package com.linc.concurrency;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicLong;

public class ConcurrencyDemo {

  private static AtomicLong aLong = new AtomicLong(0);

  public static void main(String[] args) throws InterruptedException, ExecutionException {

    // 1. 实现runnable接口的对象, 用来实例化一个新的线程
    Runnable runnable =
        () -> {
          // 这个线程要做的事情
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          System.out.println(
              "From runnable impl"
                  + Thread.currentThread().getId()
                  + Thread.currentThread().getName());
        };

    Runnable r =
        new Runnable() {
          @Override
          public void run() {
            try {
              Thread.sleep(1000);
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
            System.out.println(
                "From runnable Interface :Thread: "
                    + Thread.currentThread().getId()
                    + ": "
                    + Thread.currentThread().getName());
          }
        };

    var t = new Thread(r);
    t.start();

    // 2. 继承Thread类, 重写run方法, 不怎么推荐,
    // 原因是将对象和对象的调用混合在一起了
    // 例如下面这个例子, 如果要启动多个线程, 则需要创建多个Task的实例
    var task = new Task();
    task.start();

    // 3. callable可以得到返回值

    var callTask = new CallableTask();
    FutureTask<Long> futureTask = new FutureTask<>(callTask);
    var callThread = new Thread(futureTask);
    callThread.start();

    var futureR = futureTask.get();
    System.out.println("future return " + futureR);

    System.out.println(
        "From main method: Thread: "
            + Thread.currentThread().getId()
            + ": "
            + Thread.currentThread().getName());

    //    Thread.sleep(1000);

  }

  static class Task extends Thread {
    @Override
    public void run() {
      System.out.println(
          "From subclass of Thread: "
              + " Thread: "
              + Thread.currentThread().getId()
              + ": "
              + Thread.currentThread().getName());
    }
  }

  static class CallableTask implements Callable<Long> {

    @Override
    public Long call() throws Exception {
      Thread.sleep(100);
      return System.currentTimeMillis();
    }
  }
}
